// MdSpi.h: interface for the CMdSpi class.
//
//////////////////////////////////////////////////////////////////////

#ifndef MDSPI_H
#define MDSPI_H

#define MD_OK 1000000

#include "string.h"
#include "ThostFtdcMdApi.h"
#include "Config.h"
#include "qtapi.h"
#include "AllMarketData.h"
#include "Event.h"
#include "pthread.h"

#include <map>
#include <set>
#include <string>

using namespace std;

class CMdSpi2 : public CThostFtdcMdSpi
{
public:
	void*  m_pMd;
private:
	char  				m_cIniFile[64];

	CMyConfig2*			m_pConfig3;
	bool				m_bOnline;
	int 				m_nLastError;
	char 				m_cLastError[256];
	CEvent 				m_hEvent;
	CThostFtdcMdApi*	m_pMdApi;
	map<string,int>		m_SubScribeCount;
	CLock				m_SubLock;
	CLock				m_ListenerLock;
	CAllMarketData*		m_pAllMarketData3;
	list<IMarketDataListener*>  m_Listeners;
	pthread_t 			m_pthread;

public:
	CMdSpi2();

	CMdSpi2(const char *pszInitFile);

	virtual ~CMdSpi2();

	void InitMyConfig(const char * pszInitFile);

	void OnFrontConnected();

	void OnFrontDisconnected(int nReason);

	void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);

	void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData);

	virtual void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
		if(pRspInfo && pSpecificInstrument){
			m_SubLock.Lock();
			if(pRspInfo->ErrorID==0){
				this->m_SubScribeCount[pSpecificInstrument->InstrumentID] = MD_OK;
			}
			m_SubLock.Unlock();
		}
	};

	//subscribe market data;
	int SubscribeMarketData(const char * code);

	//unsubscribe market data;
	void UnsubscribeMarketData(const char * code);

	virtual int	Login(const char* UserID,const char* Password,char* ErrorMsg,int* ErrorID);

	//login to the md server;
	int Login(const char *pszUserID,const char *pszPassword);

	void AddListener(IMarketDataListener*  pListener);

	void RemoveListener(IMarketDataListener*  pListener);

	void Stop();

	void Release();

	void Check() {
		/*m_SubLock.Lock();
		map<string,int>::iterator it = this->m_SubScribeCount.begin();
		map<string,int>::iterator end = this->m_SubScribeCount.end();
		while(it != end){
			if(it->second<MD_OK){
				char**  ppIns = new char*[1];
				ppIns[0]= new char[64];
				strcpy(ppIns[0],it->first.c_str());
				m_pMdApi->SubMarketData(ppIns,1);
				delete[] ppIns[0];
				delete[] ppIns;
			}
			it++;
		}
		m_SubLock.Unlock();*/

	};
};

class CCtpFutureMD:public IFutureMD{
private:
	set<string> m_Instruments;

public:
	CMdSpi2* m_pSpi;

	/**
	 *login to trade;
	 */
	virtual int		Login(const char* UserID,const char* Password,char* ErrorMsg,int* ErrorID);

	virtual int		SubscribeMarketData(const char *InstrumentID);

	virtual void	UnsubscribeMarketData(const char *InstrumentID);

	virtual void	AddListener(IMarketDataListener* pListener);

	virtual void	RemoveListener(IMarketDataListener* pListener);

	virtual void 	Stop();

	virtual void	Release();
};

extern "C"{
	IFutureMD* CreateMD(const char *pszConfigFile);
}


#endif // !defined(AFX_MDSPI_H__3C031545_5A01_4959_9514_B375EEA8D4DD__INCLUDED_)
